package com.syh.jn.scm.service.impl.supplier.sale;

import cn.redscarf.commons.util.bean.ExtBeanUtils;
import cn.redscarf.commons.util.other.ExtAssert;
import cn.redscarf.commons.wrapper.Restrictions;
import cn.redscarf.commons.wrapper.Wrapper;
import com.alibaba.dubbo.config.annotation.Service;
import com.syh.core.ddd.event.annotation.DomainEventHandle;
import com.syh.core.ddd.infrastructure.repository.AggregateRepository;
import com.syh.core.ddd.service.AbstractServiceImpl;
import com.syh.jn.scm.domain.driver.entity.logistics.DriverLogisticsBill;
import com.syh.jn.scm.domain.driver.event.DriverLogisticsBillEvent;
import com.syh.jn.scm.domain.operation.entity.supplier.OperaSupplier;
import com.syh.jn.scm.domain.operation.event.supplier.OperaSupplierEvent;
import com.syh.jn.scm.domain.supplier.entity.finance.StatementAccountBill;
import com.syh.jn.scm.domain.supplier.entity.logistics.LogisticsBill;
import com.syh.jn.scm.domain.supplier.entity.sale.SaleReturnOrder;
import com.syh.jn.scm.domain.supplier.entity.sale.SaleReturnOrderItem;
import com.syh.jn.scm.domain.supplier.event.LogisticsBillEvent;
import com.syh.jn.scm.domain.supplier.event.SaleReturnOrderEvent;
import com.syh.jn.scm.domain.supplier.event.finance.BusinessAccountRecordEvent;
import com.syh.jn.scm.domain.supplier.event.finance.StatementAccountBillEvent;
import com.syh.jn.scm.domain.supplier.repository.logistics.LogisticsBillRepository;
import com.syh.jn.scm.domain.supplier.repository.sale.SaleReturnOrderRepository;
import com.syh.jn.scm.dto.supplier.sale.SaleReturnOrderItemVo;
import com.syh.jn.scm.dto.supplier.sale.SaleReturnOrderMto;
import com.syh.jn.scm.dto.supplier.sale.SaleReturnOrderSto;
import com.syh.jn.scm.dto.supplier.sale.SaleReturnOrderVo;
import com.syh.jn.scm.dto.support.FilesDto;
import com.syh.jn.scm.service.api.supplier.finance.enums.StatementAccountBillEnum;
import com.syh.jn.scm.service.api.supplier.logistics.enums.LogisticsBillEnums;
import com.syh.jn.scm.service.api.supplier.sale.SaleReturnOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * Date:2018/7/17
 * Author:Clown
 * 供应商销售退货service实现;
 */
@Service
@Transactional
public class SaleReturnOrderServiceImpl extends AbstractServiceImpl<SaleReturnOrderSto, SaleReturnOrderMto, SaleReturnOrderVo, SaleReturnOrder, Long> implements SaleReturnOrderService {
  @Autowired
  private SaleReturnOrderRepository saleReturnOrderRepository;
  @Autowired
  private LogisticsBillRepository logisticsBillRepository;

  @Override
  protected AggregateRepository<SaleReturnOrder, Long> getAggregateRepository() {
    return saleReturnOrderRepository;
  }

  /**
   * 判空方法
   *
   * @param id
   * @return
   */
  private SaleReturnOrder judgeNull(Long id) {
    ExtAssert.notNull(id, "id不能为空");
    SaleReturnOrder entity = saleReturnOrderRepository.getById(id);
    ExtAssert.notNull(entity, "订单不存在");
    return entity;
  }

  /**
   * 新增销售退货单
   *
   * @param sto
   * @return
   */
  @Override
  public Long save(SaleReturnOrderSto sto) {
    SaleReturnOrder saleReturnOrder = SaleReturnOrder.createBySupply(sto);
    Long orderId = saleReturnOrderRepository.add(saleReturnOrder);
    this.publicEvent(SaleReturnOrderEvent.buildSaleReturnOrderCreated(new Object[]{saleReturnOrder}));
    return orderId;
  }

  /**
   * 修改销售退货单
   *
   * @param mto
   */
  @Override
  public void update(SaleReturnOrderMto mto) {
    SaleReturnOrder order = judgeNull(mto.getId());
    SaleReturnOrder oldOrder = saleReturnOrderRepository.getById(mto.getId());
    order.modify(mto);
    saleReturnOrderRepository.update(order);
    this.publicEvent(SaleReturnOrderEvent.buildSaleReturnOrderUpdated(new Object[]{order,oldOrder}));
  }

  /**
   * 根据id删除订单
   *
   * @param id
   */
  @Override
  public void delete(Long id) {
    SaleReturnOrder order = judgeNull(id);//判空
    order.destory();
    saleReturnOrderRepository.remove(order);
  }


  /**
   * 根据id取消订单
   *
   * @param id
   */
  @Override
  public void cancel(Long id) {
    SaleReturnOrder order = judgeNull(id);
    order.cancel();
    saleReturnOrderRepository.updateStatus(order);
    this.publicEvent(SaleReturnOrderEvent.buildSaleReturnOrderCancel(new Object[]{order}));
  }

  /**
   * 根据id确认订单
   *
   * @param id
   */
  @Override
  public void confirm(Long id) {
    SaleReturnOrder order = judgeNull(id);
    order.confirm();
    saleReturnOrderRepository.updateStatus(order);
  }

  /**
   * 反确认订单
   *
   * @param id
   */
  public void antiConfirm(Long id) {
    SaleReturnOrder order = judgeNull(id);
    order.cancelConfirm();
    saleReturnOrderRepository.updateStatus(order);
  }

  /**
   * 根据id查询商品明细
   *
   * @param id
   * @return
   */
  @Override
  public List<SaleReturnOrderItemVo> getItemsBySaleReturnOrderId(Long id) {
    return this.transformSaleReturn(saleReturnOrderRepository.getItemsBySaleReturnOrderId(id));
  }

  /**
   * 根据ids获取明细
   *
   * @param ids
   * @return
   */
  @Override
  public List<SaleReturnOrderItemVo> getItemsBySaleReturnOrderIds(Long[] ids) {
    return this.transformSaleReturn(saleReturnOrderRepository.getItemsBySaleReturnOrderIds(ids));
  }

  /**
   * 上传单据图片
   *
   * @param dto
   */
  @Override
  public void uploadImages(FilesDto dto) {
    SaleReturnOrder order = judgeNull(dto.getId());
    order.upload(dto);
    saleReturnOrderRepository.uploadImages(order);
  }

  /**
   * 批量新增退货订单
   *
   * @param stoList
   * @return
   */
  @Override
  public List<Long> batchSave(List<SaleReturnOrderSto> stoList) {
    List<Long> ids = new ArrayList<>();
    stoList.stream().forEach(sto -> {
      Long id = this.save(sto);
      ids.add(id);
    });
    return ids;
  }

  /**
   * 消费者：监听物流单收货（修改发货数量）
   */
  @DomainEventHandle(BusinessAccountRecordEvent.BUSINESS_ACCOUNT_RECORD_CHECK_DISCOUNT_AFTER)
  protected void handleLogisticsBillCollected(LogisticsBill bill) {
    if (LogisticsBillEnums.OrderType.RETURN_SALE.getStatus().equals(bill.getOrderType())) {
      SaleReturnOrder order = saleReturnOrderRepository.getById(bill.getOrderId());
      order.collect(bill);
      saleReturnOrderRepository.updateOrderAndItems(order);
    }
  }

  /**
   * 消费者：监听物流单取消收货（修改发货数量）
   */
  @DomainEventHandle(BusinessAccountRecordEvent.BUSINESS_ACCOUNT_RECORD_CHECK_DISCOUNT_BEFORE)
  protected void handleLogisticsBillUnReceived(LogisticsBill bill) {
    if (LogisticsBillEnums.OrderType.RETURN_SALE.getStatus().equals(bill.getOrderType())) {
      SaleReturnOrder order = saleReturnOrderRepository.getById(bill.getOrderId());
      order.cancelCollect(bill);
      saleReturnOrderRepository.updateOrderAndItems(order);
    }
  }

  /**
   * 消费者：监听对账单（生成对账单状态和对账单号）
   *
   * @param bill
   */
  @DomainEventHandle(StatementAccountBillEvent.STATEMENT_BILL_ACCOUNT_CREATED)
  protected void handleStatementBillAccountCreated(StatementAccountBill bill) {
    bill.getStatementAccountBillItems().forEach(billItem -> {
      if (billItem.getSourceType().equals(StatementAccountBillEnum.SOURCE_SALE_RETURN_ORD.getStatus())) {
        SaleReturnOrder saleReturnOrder = saleReturnOrderRepository.getById(billItem.getSourceId());
        saleReturnOrder.generating(bill.getId());
        saleReturnOrderRepository.updateStatus(saleReturnOrder);
      }
    });
  }

  /**
   * 消费者：监听对账单（修改对账单状态）
   *
   * @param bill
   */
  @DomainEventHandle(StatementAccountBillEvent.STATEMENT_BILL_ACCOUNT_UPDATA)
  protected void handleStatementBillAccountUpdata(StatementAccountBill bill) {
    Wrapper wrapper = Wrapper.build();
    wrapper.append(Restrictions.eq("statementId", bill.getId()));
    List<SaleReturnOrder> saleReturnOrders = saleReturnOrderRepository.getList(wrapper);
    saleReturnOrders.forEach(saleReturnOrder -> {
      saleReturnOrder.cancelGenerating();
      saleReturnOrderRepository.updateStatus(saleReturnOrder);
    });
    bill.getStatementAccountBillItems().forEach(billItem -> {
      if (billItem.getSourceType().equals(StatementAccountBillEnum.SOURCE_SALE_RETURN_ORD.getStatus())) {
        SaleReturnOrder saleReturnOrder = saleReturnOrderRepository.getById(billItem.getSourceId());
        saleReturnOrder.generating(bill.getId());
        saleReturnOrderRepository.updateStatus(saleReturnOrder);
      }
    });
  }

  /**
   * 消费者：监听对账单（删除对账单状态和对账单号）
   *
   * @param bill
   */
  @DomainEventHandle(StatementAccountBillEvent.STATEMENT_BILL_ACCOUNT_DESTROY)
  protected void handleStatementBillAccountDestroy(StatementAccountBill bill) {
    bill.getStatementAccountBillItems().forEach(billItem -> {
      if (billItem.getSourceType().equals(StatementAccountBillEnum.SOURCE_SALE_RETURN_ORD.getStatus())) {
        SaleReturnOrder saleReturnOrder = saleReturnOrderRepository.getById(billItem.getSourceId());
        saleReturnOrder.cancelGenerating();
        saleReturnOrderRepository.updateStatus(saleReturnOrder);
      }
    });

  }

  /**
   * 消费者：监听服务商反开账（删除所有该服务商的销售退货单）
   */
  @DomainEventHandle(OperaSupplierEvent.SUPPLIER_REVERSAL_ACCOUNT)
  protected void handleSupplierReversalAccount(OperaSupplier supplier) {
    this.saleReturnOrderRepository.deleteByBusinessEntityId(supplier.getId());
  }

  /**
   * 内部方法  业务模型转传输对象
   *
   * @param entityList
   * @return
   */
  private List<SaleReturnOrderItemVo> transformSaleReturn(List<SaleReturnOrderItem> entityList) {
    List<SaleReturnOrderItemVo> voList = new ArrayList<>();
    entityList.stream().forEach((entity) -> {
      SaleReturnOrderItemVo vo = new SaleReturnOrderItemVo();
      ExtBeanUtils.copyProperties(entity, vo);
      voList.add(vo);
    });
    return voList;
  }
}
